import unittest

import sys

sys.path.append('../..')


class TestGroup:

	updated = False
	drawn = False

	def __init__(self):
		self.particles = set()
	
	def __iter__(self):
		# Iterate a copy to tolerate mutation during iteration
		return iter(set(self.particles))
	
	def update(self, td):
		self.updated = True
		self.time_delta = td
	
	def draw(self):
		self.drawn = True


class TestController:

	def __init__(self):
		self.groups = set()
	
	def __call__(self, td, group):
		self.groups.add(group)
		self.time_delta = td


class SystemTest(unittest.TestCase):

	def test_add_remove_group(self):
		""""""
		from particle import ParticleSystem
		system = ParticleSystem()
		self.failIf(system.groups)
		test_group = object()
		system.add_group(test_group)
		self.assertEqual(len(system.groups), 1)

		system.remove_group(test_group)
		self.assertEqual(len(system.groups), 0)
	
		self.assertRaises(ValueError, system.remove_group, test_group)

	def test_len_contains_iter(self):
		"""Test built in __len__, __contains__, __iter__"""
		from particle import ParticleSystem
		system = ParticleSystem()
		test_group = object()
		self.assertFalse(test_group in system)
		self.assertEqual(list(iter(system)), [])
		system.add_group(test_group)
		self.assertEqual(len(system), 1)
		self.assertEqual(len(system.groups), len(system))
		self.assertTrue(test_group in system)
		self.assertEqual(list(iter(system)), [test_group])
		another_group = object()
		self.assertFalse(another_group in system)
		system.add_group(another_group)
		self.assertTrue(another_group in system)
		self.assertEqual(list(iter(system)), [test_group, another_group])

	def test_add_global_controllers(self):
		from particle import ParticleSystem
		system = ParticleSystem()
		test_controller = TestController()
		self.assertEqual(len(system.controllers), 0)
		system.add_global_controller(test_controller)
		self.assertEqual(len(system.controllers), 1)
		self.assertEqual(list(system.controllers), [test_controller])

	def test_pkg_default_system(self):
		from particle import ParticleSystem, default_system
		self.failUnless(isinstance(default_system, ParticleSystem))
	
	def test_update(self):
		from particle import ParticleSystem
		system = ParticleSystem()
		group1 = TestGroup()
		group2 = TestGroup()
		system.add_group(group1)
		system.add_group(group2)
		self.failIf(group1.updated)
		self.failIf(group2.updated)
		system.update(0.05)
		self.failUnless(group1.updated)
		self.failUnless(group2.updated)

	def test_draw(self):
		from particle import ParticleSystem
		system = ParticleSystem()
		group1 = TestGroup()
		group2 = TestGroup()
		system.add_group(group1)
		system.add_group(group2)
		self.failIf(group1.drawn)
		self.failIf(group2.drawn)
		system.draw()
		self.failUnless(group1.drawn)
		self.failUnless(group2.drawn)


if __name__=='__main__':
	unittest.main()
